GO
Shell脚本开发规范及习惯非常重要,有了好的规范和习惯,才能大大提升开发效率,降低后期的脚本维护成本,特别是在多人协作开发时,有一个互相遵守的规范显得特别重要。即使是自己一个人独自开发,也要采取一套科学的、固定的规范,这样脚本才更易读,易于后期维护。总之,就是要让自己养成一个一出手就是专业和规范的习惯。
1. Shell脚本基本规范
1.1. 一些基本规范
- 在Shell脚本里,第一行通常用于指定脚本解释器。
- 该行内容为:
#!/bin/bash
或#!/bin/sh
。 - 说明:此项在Linux系统场景下可能不是必须的,属于优秀规范和习惯
- 该行内容为:
在Shell脚本的开头处解释器代码后,最好加上版本版权等信息,如下:
12345#Date: 13:30 2018-03-01#Author: Theshu#Mail: theshu@qq.com#Function: This scripts function is...#Version: 0.1- 说明:可以在
~/.vimrc
配置文件时自动加上以上信息的功能。此项在Linux系统场景下不是必须的,属于优秀规范和习惯。
- 说明:可以在
- Shell脚本中尽量不要用中文注释,应用英文注释,以防止本机或切换系统环境后出现中文乱码的困扰。如果非要加中文,请根据自身的客户端对系统进行字符集调整,如:
export LANG="zh_CN.UTF-8"
,并在脚本中重新定义字符集,使其和系统一致。 - Shell脚本命名应以
.sh
为扩展名。例如:script-name.sh
- Shell脚本应存放在固定的路径下,例如:
/server/scripts
1.2. 代码书写技巧
成对的符号应尽量一次写出来,然后退格在符号里增加内容,以防止遗漏。这些成对的符号包括:
1{}、[]、''、``、""中括号
[]
两端至少要有一个空格,因此,键入中括号的时候即可留出空格[ ]
,然后再退格键入中间的内容,并确保两端都至少有一个空格。即:先键入一对中阔后,然后退一个格,输入两个空格,再退一个格,双中括号[[]]
的写法也是如此。对于流程控制语句应一次将格式写完,再添加内容。
比如:if语句的格式一次完成应为
1234if 条件内容then内容fi再比如:for循环语句的格式一次完成应为
1234fordo内容done提示:while和until、case等语句也是一样。
通过缩进让代码更易读,比如:
12345678if 条件内容then内容fi############if 条件内容; then内容fi字符串赋值给变量时应加双引号,并且等号前后不能有空格。例如:
THESHU_FILE="test.txt"
- 脚本中的单引号、双引号及反引号,必须为英文状态下的符号,其实所有的Linux标准字符及符号都应该是英文状态下的符号,这一点需要特别注意。
2. Shell脚本变量命名及引用变量规范
2.1. 全局变量定义
全局变量也称环境变量,它的定义应全部大写,如APACHE_ERR
或APACHEERR
,名字对应的语义要尽量清晰,能够正确表达变量内容的含义,对于过长的英文单词可用前几个字符代替。多个单词间可用_
符号连接,全局变量的定义一般放在系统的全局路径中,并且最好蚕蛹export
来定义,全局变量一般可以在任意子Shell中直接使用(特殊情况除外,例如:定时任务执行Shell时就最好在Shell里重新定义这些全局变量,否则可能会出现问题)。
2.2. 局部变量定义
局部变量也成为普通变量,在常规脚本中,普通变量的命名也要尽可能统一,可以使用用驼峰语法,即第二个单词的首字母大写,如theshuHome
,或者每个单词首字母大写,如TheshuHome
,当然也有人喜欢采用全部大写或全部小写的方式,例如:theshuhome
、THESHUHOME
。选择一种适合自己的方式即可。
Shell函数中的变量可以使用local
方式进行定义,使之只在本函数作用域内有效,防止函数中的变量名称与外部程序中的变量相同,从而造成程序异常。下面是在函数中定义变量的例子:
2.3. 变量的引用规范
在引用变量时,若变量前后都有字符,则需要使用${APACHE_ERR}
(加大括号的方式)引用变量,以防止产生歧义;当变量内容为字符串时,需要使用"${APACHE_ERR}"
(外面加双引号的方式)引用变量;当变量内容为整数时,则最好直接使用$APACHE_ERR
来引用变量。全局变量、局部变量、函数变量、数组变量等都是如此。
- 说明:对于需要环境变量的Java程序脚本等,在写脚本之前,最好通过export重新声明环境变量,一面在定时任务等场合的使用中出现问题。
3. Shell函数的命名及函数定义规范
Shell函数的命名可采用单词首字母大写的形式,如CreateFile()
,并且语义要清晰,比如,使用CreateFile()
代替CFILE()
。也可以使用小写形式,如createfile()
。
可以加前后缀,如后缀为Max
则为最大值,为Min
则表示最小值,前缀Is
为判断型函数,Get
为取值函数,Do
则为处理函数,这也有益于对函数功能的理解,使函数名更直观、更清晰。
范例:对操作系统函数库脚本的函数名进行定义:
如果需要区别一些常规的字符串,可在函数名前加上function
关键字,如下:
显示函数返回值时,可在函数的结尾内容中包含return语句
,并跟上返回值。即使是不关心返回值的函数,也可能在后续调用时无意识地去判断它的返回值并进行一系列动作,使用return语句不会带来多少负担,但确实能让函数的逻辑变得更加清晰和严谨。
范例:为操作系统函数库脚本函数定义return返回值
4. Shell脚本(模块)高级命名规范
- 常规的Shell脚本使用统一的后缀:
.sh
,例如theshu.sh
- 模块的启动和停止脚本统一命名为
start_模块名.sh
和stop_模块名.sh
- 监控脚本通常以
*_mon.sh
为后缀 - 控制脚本一般以
*_ctl.sh
为后缀
5. Shell脚本的代码风格
5.1 代码框架
易变的信息(如报警的收件人、机器名、用户名密码、URL等)最好都定义为变量或使用特殊位置的参数,这会使开发的脚本更具通用性。
把Shell的通用变量以配置文件的形式单独存放,以功能.cfg
来命令,例如nginx.conf
,并放在conf目录下;引用时通过在脚本开头使用conf/nginx.conf
的形式来加载。
将程序的功能分段、分模块采用函数等来实现,并存放到单独的函数文件里,如过是通用的公共函数可以存放在/etc/init.d/functions
下,调用时采用source 文件全路径
即可。
把脚本中的功能和配置明确分开,主脚本只用于实现程序主干,加载配置及加载函数等功能实现应尽量封装在子函数中。
规范代码树如下:
5.2. 缩进规范
在使用条件语句时,每进行一层循环或是循环内部的操作时,就使用一个缩进,缩进一般用Tab
键加空格
。推荐采用4个空格缩进。
范例:写出脚本缩进规范:
提示:可调整Vim实现自动缩进,建议缩进4个空格。
6. Shell脚本的变量及文件检查规范
脚本中要检查配置项是否为空、是否可执行等,尤其是对于一些重要的、会影响下面脚本正常运行的配置想,必须要进行是否为空等的检查,避免配置文件中出现遗漏等问题。
范例:针对字符串变量进行判断:
范例:给出HTTP脚本变量的定义方式:
提示:这样的定义可以防止变量出现空着,这是变量子串的特殊知识。
OK